Deploy Prompter on the Cratis cluster, and plan the docs-gap and GitHub surfaces - #2
Conversation
Deployment code, not a deployment: a Pulumi C# project modeled on Studio's, which is the reference implementation for this cluster. It keeps Studio's conventions deliberately — self-managed file://./state committed to Git, the passphrase secrets provider, and a scripts/set-secrets.sh for the runtime secrets. The one place it departs is ownership. Studio's stack creates the UKS cluster, the NGINX controller, the cert-manager issuer and the upcloud-maxiops StorageClass; this stack looks the cluster up by id and declares nothing cluster-scoped, so everything it creates lives inside the prompter-production namespace and the two stacks cannot collide (D-15). What it provisions: Postgres with pgvector as a single-replica StatefulSet (same image as local compose and the eval workflow), the bot as a single-replica Deployment with the Recreate strategy — the Discord gateway wants exactly one connection — and an ingress that publishes only POST /reindex, leaving /healthz cluster-internal. Probe asymmetry is intentional: readiness uses /healthz (database + gateway), liveness is a TCP check, because /healthz reports unhealthy during a Discord outage and restart-looping would fix nothing while taking the re-index endpoint down with it. Builds clean in the solution; nothing has been applied to the cluster. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015LV2femm3ZR47Lk2SscwJb
deploy-production.yml mirrors Studio's: pin the image tag with `pulumi config set` (which preserves the config file's comments, unlike a raw YAML edit), run `pulumi up` against the file backend on the self-hosted cratis runner, then commit the updated state back with [skip ci]. Publish calls it as a workflow_call after publish-docker, so a failed image push can never deploy a tag that does not exist. workflow_dispatch stays available for redeploying or rolling back to any version by hand. Needs two repository secrets that do not exist yet: PULUMI_CONFIG_PASSPHRASE and UPCLOUD_TOKEN. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015LV2femm3ZR47Lk2SscwJb
Three things the planning docs were missing or had wrong. Release mechanics: nothing has ever been released. cratis/release-action only cuts a release for a merged PR labeled major/minor/patch, PR #1 carried none, so Publish ran, decided should-publish=false and did nothing — successfully, which is why it went unnoticed. Docker Hub has no cratis/prompter repository and there are no releases. DEPLOYMENT.md now documents the label rule and how to cut the first version. D-15 answers Q-5 and reverses D-11's recommendation: Prompter's Pulumi code lives here, not in Studio's stack. Reading Studio's deploy workflow is what settled it — it pins one version across every Studio image, so a prompterImage entry there would need its own workflow and a cross-repo dispatch anyway, while making every Prompter release re-evaluate MongoDB, Chronicle and the AuthProxies. Marked OPEN: it is their cluster, so the team confirms. Docs-gap flywheel (P-33) rewritten around its two possible feeds, because the idea of Prompter filing docs-gap issues runs straight into D-13 — the interaction log keeps no question text, so there is nothing to mine today. Feed A is a "this should be documented" button (P-45): the click is the consent, the text is forwarded and never stored, and D-13 stands untouched. Feed B needs D-14, added as an OPEN decision recommending A first. P-44 adds the GitHub issues surface — the same answering behind a webhook, silent on refusal — which also closes the loop cheaply, since a refusal on an issue is a docs gap already in a tracker. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015LV2femm3ZR47Lk2SscwJb
The self-hosted runner label queues indefinitely rather than failing when it is not available to a repository, and a `production` environment with required reviewers pauses the deploy. Both are fine — they just should not be discovered during the first release. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015LV2femm3ZR47Lk2SscwJb
The stack has never been applied and its secrets may not exist yet, so calling it from Publish would turn every release red until the cluster side is set up. A `secrets` context cannot be read from a job-level `if`, so a small job checks the two secrets plus an initialized Deployment/state and the deploy is gated on its output. Publishing an image stays green on its own; the skip is reported as a notice naming exactly what is missing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015LV2femm3ZR47Lk2SscwJb
|
Reviewer context — none of this is user-facing, so it is here rather than in the body. Where the deployment code lives. D-11 recommended making Prompter a workload in Studio's This stack owns nothing cluster-scoped. The cluster, node group, NGINX controller, cert-manager Probe asymmetry is deliberate. Readiness uses Nothing has been applied. This is unrun infrastructure code. Before a real deploy: Planning changes ride along. P-33 (docs-gap flywheel) is rewritten around its two possible feeds, since filing issues about undocumented questions runs straight into D-13 — the interaction log keeps no question text, so there is nothing to mine today. P-45 is the unblocked feed (a "this should be documented" button; the click is the consent, nothing is stored), P-44 adds a GitHub-issues answering surface, and D-14 records the genuinely open question — whether question text is stored at all — recommending "not yet". Q-7 asks which repository receives a docs-gap issue. Verification. |
Summary
Prompter's first release: the bot can now be deployed to the Cratis UpCloud Kubernetes cluster from a released version.
Added
POST /reindex(P-21).Deploy - Productionworkflow that pins the released image tag, applies the stack, and redeploys or rolls back any version on demand (P-21).Changed
major,minororpatch, or a manual dispatch with an explicit version (P-26).